컨ν μ€νΈ κΈ°λ° μ€νμΌλ§μ μν μ‘°κ±΄λΆ μΊμ€μΌμ΄λ λ μ΄μ΄ νμ±νλ₯Ό ν΅ν΄ κ³ κΈ CSS μν€ν μ²λ₯Ό νμνμΈμ.
CSS Cascade Layer μ‘°κ±΄λΆ νμ±ν: μν© μΈμ μ€νμΌλ§ μ¬μΈ΅ λΆμ
μμ λ λμ CSSλ₯Ό λκ·λͺ¨λ‘ κ΄λ¦¬νλ κ²μ μΉ κ°λ°μμ κ°μ₯ μ§μμ μΈ κ³Όμ μ€ νλμμ΅λλ€. μ°λ¦¬λ μ μ μ€νμΌμνΈμ "μΌμ μλΆ"μμ BEMκ³Ό κ°μ ꡬ쑰νλ λ°©λ²λ‘ μΌλ‘, Sassμ κ°μ μ μ²λ¦¬κΈ°λ‘λΆν° CSS-in-JSλ₯Ό μ¬μ©ν μ»΄ν¬λνΈ λ²μ μ€νμΌλ‘ μ¬μ μ κ±°μ³€μ΅λλ€. κ° μ§νλ CSS νΉμμ±κ³Ό μ μ μΊμ€μΌμ΄λμ μΌμλ₯Ό κΈΈλ€μ΄λ κ²μ λͺ©νλ‘ νμ΅λλ€. CSS μΊμ€μΌμ΄λ λ μ΄μ΄(@layer)μ λμ μ κ°λ°μμκ² μΊμ€μΌμ΄λμ λν λͺ μμ μΈ μ μ΄λ₯Ό μ 곡νλ νκΈ°μ μΈ λ°μ μ΄μμ΅λλ€. νμ§λ§ μ΄ μ μ΄λ₯Ό ν λ¨κ³ λ λ°μ μν¬ μ μλ€λ©΄ μ΄λ¨κΉμ? μ€νμΌμ μμλ₯Ό μ νλ κ²λΏλ§ μλλΌ μ¬μ©μμ μν©μ λ°λΌ 쑰건λΆλ‘ νμ±νν μλ μλ€λ©΄ μ΄λ¨κΉμ? μ΄κ²μ΄ λ°λ‘ νλ CSS μν€ν μ²μ μ΅μ μ μΈ μν© μΈμ λ μ΄μ΄ λ‘λ©μ λλ€.
μ‘°κ±΄λΆ νμ±νλ νμν λλ§ CSS λ μ΄μ΄λ₯Ό λ‘λνκ±°λ μ μ©νλ κ΄νμ λλ€. μ΄ μ»¨ν μ€νΈλ μ¬μ©μμ λ·°ν¬νΈ ν¬κΈ°, μ νΈνλ μμ ꡬμ±ν, λΈλΌμ°μ κΈ°λ₯ λλ JavaScriptλ‘ κ΄λ¦¬λλ μ ν리μΌμ΄μ μν λ± λ¬΄μμ΄λ λ μ μμ΅λλ€. μ΄ μ κ·Ό λ°©μμ μ±νν¨μΌλ‘μ¨ μ°λ¦¬λ λ¨μν λ μ ꡬμ±λ μ ν리μΌμ΄μ λΏλ§ μλλΌ μ£Όμ΄μ§ μ¬μ©μ κ²½νμ νμν μ€νμΌλ§ μ 곡νμ¬ ν¨μ¬ λ λμ μ±λ₯μ λ°ννλ μ ν리μΌμ΄μ μ ꡬμΆν μ μμ΅λλ€. μ΄ λ¬Έμλ μ§μ μΌλ‘ κΈλ‘λ²νκ³ μ΅μ νλ μΉμ μν΄ CSS μΊμ€μΌμ΄λ λ μ΄μ΄λ₯Ό 쑰건λΆλ‘ νμ±ννλ μ λ΅κ³Ό μ΄μ μ ν¬κ΄μ μΌλ‘ νꡬν©λλ€.
κΈ°μ΄ μ΄ν΄: CSS μΊμ€μΌμ΄λ λ μ΄μ΄ 볡μ΅
μ‘°κ±΄λΆ λ‘μ§μ μμνκΈ° μ μ CSS μΊμ€μΌμ΄λ λ μ΄μ΄κ° 무μμΈμ§, κ·Έλ¦¬κ³ κ·Έκ²μ΄ ν΄κ²°νλ λ¬Έμ λ₯Ό νμ€ν μ΄ν΄νλ κ²μ΄ μ€μν©λλ€. ν΅μ¬μ μΌλ‘ @layer at-ruleμ μ¬μ©νλ©΄ κ°λ°μκ° λͺ λͺ λ λ μ΄μ΄λ₯Ό μ μνμ¬ μ€νμΌμ μν λͺ μμ μ΄κ³ μμκ° μ§μ λ λ²ν·μ λ§λ€ μ μμ΅λλ€.
λ μ΄μ΄μ μ£Όμ λͺ©μ μ μΊμ€μΌμ΄λλ₯Ό κ΄λ¦¬νλ κ²μ λλ€. μ ν΅μ μΌλ‘ νΉμμ±μ μ νμ 볡μ‘μ±κ³Ό μμ€ μμμ μ‘°ν©μΌλ‘ κ²°μ λμμ΅λλ€. μ΄λ μ’ μ’ "νΉμμ± μ μ"μΌλ‘ μ΄μ΄μ‘λλ°, κ°λ°μλ€μ μ μ λ 볡μ‘ν μ νμ(μ: #sidebar .user-profile .avatar)λ₯Ό μμ±νκ±°λ μ€νμΌμ μ¬μ μνκΈ° μν΄ λμ°ν !importantμ μμ‘΄νμ΅λλ€. λ μ΄μ΄λ μΊμ€μΌμ΄λμ μλ‘κ³ λ κ°λ ₯ν κΈ°μ€μΈ λ μ΄μ΄ μμλ₯Ό λμ ν©λλ€.
λ μ΄μ΄κ° μ μλλ μμλ μ°μ μμλ₯Ό κ²°μ ν©λλ€. λμ€μ μ μλ λ μ΄μ΄μ μ€νμΌμ μ νμ νΉμμ±μ κ΄κ³μμ΄ λ¨Όμ μ μλ λ μ΄μ΄μ μ€νμΌμ μ¬μ μν©λλ€. λ€μμ κ°λ¨ν μ€μ μ λλ€.
// λ μ΄μ΄ μμλ₯Ό μ μν©λλ€. μ΄κ²μ΄ μ μΌν μ§μ€ 곡κΈμμ
λλ€.
@layer reset, base, components, utilities;
// 'components' λ μ΄μ΄μ μ€νμΌ
@layer components {
.button {
background-color: blue;
padding: 10px 20px;
}
}
// 'utilities' λ μ΄μ΄μ μ€νμΌ
@layer utilities {
.bg-red {
background-color: red;
}
}
μ΄ μμμ <button class="button bg-red">Click Me</button>μ κ°μ μμλ₯Ό κ°μ§κ³ μλ€λ©΄ λ²νΌμ λ°°κ²½μ λΉ¨κ°μμ΄ λ©λλ€. μλκ³ μ? utilities λ μ΄μ΄κ° components λ μ΄μ΄λ³΄λ€ λμ€μ μ μλμμΌλ―λ‘ μ°μ μμκ° λ λκΈ° λλ¬Έμ λλ€. κ°λ¨ν ν΄λμ€ μ νμ .bg-redλ λμΌν μ νμ νΉμμ±μ κ°μ§κ³ μμμλ λΆκ΅¬νκ³ .buttonμ μ¬μ μν©λλ€. μ΄ μμΈ‘ κ°λ₯ν μ μ΄λ μ‘°κ±΄λΆ λ‘μ§μ ꡬμΆν μ μλ κΈ°λ°μ λλ€.
"μ?" : μ‘°κ±΄λΆ νμ±νμ μ€μμ±
νλμ μΉ μ ν리μΌμ΄μ μ λ§€μ° λ³΅μ‘ν©λλ€. λ€μν μꡬμ μ₯μΉλ₯Ό κ°μ§ μ μΈκ³ μ¬μ©μμκ² μλΉμ€λ₯Ό μ 곡ν΄μΌ νλ©° λ€μν 컨ν μ€νΈμ μ μν΄μΌ ν©λλ€. μ΄λ¬ν 볡μ‘μ±μ μ€νμΌμνΈλ‘ μ§μ μ λ¬λ©λλ€.
- μ±λ₯ μ€λ²ν€λ: λͺ¨λ κ°λ₯ν μ»΄ν¬λνΈ λ³ν, ν λ§ λ° νλ©΄ ν¬κΈ°μ λν μ€νμΌμ ν¬ν¨νλ λ¨μΌ CSS νμΌμ λΈλΌμ°μ κ° μ¬μ©λμ§ μμ κ°λ₯μ±μ΄ λμ λ§μ μμ μ½λλ₯Ό λ€μ΄λ‘λ, ꡬ문 λΆμ λ° νκ°νλλ‘ κ°μ ν©λλ€. μ΄λ First Contentful Paint(FCP)μ κ°μ μ£Όμ μ±λ₯ μ§νμ μ§μ μ μΈ μν₯μ λ―ΈμΉλ©°, νΉν λͺ¨λ°μΌ μ₯μΉλ μΈν°λ· μ°κ²° μλκ° λλ¦° μ§μμμ λλ¦° μ¬μ©μ κ²½νμΌλ‘ μ΄μ΄μ§ μ μμ΅λλ€.
- κ°λ° 볡μ‘μ±: λ¨μΌμ κ±°λν μ€νμΌμνΈλ νμνκ³ μ μ§ κ΄λ¦¬νκΈ° μ΄λ ΅μ΅λλ€. μμ ν μ¬λ°λ₯Έ κ·μΉμ μ°Ύλ κ²μ νλ μΌμ΄ λ μ μμΌλ©° μλνμ§ μμ λΆμμ©μ νν©λλ€. κ°λ°μλ μ’ μ’ λ³κ²½νλ κ²μ λλ €μνμ¬ "λ§μ½μ μν΄" μ€λλκ³ μ¬μ©λμ§ μλ μ€νμΌμ΄ κ·Έλλ‘ λ¨μ μλ μ½λ λΆν¨λ‘ μ΄μ΄μ§λλ€.
- λ€μν μ¬μ©μ 컨ν μ€νΈ: μ°λ¦¬λ λ°μ€ν¬ν±λΏλ§ μλλΌ λͺ¨λ κ²μ μν΄ κ΅¬μΆν©λλ€. λ°μ λͺ¨λμ μ΄λμ΄ λͺ¨λ(prefers-color-scheme), μ κ·Όμ±μ μν κ³ λλΉ λͺ¨λ, μΆμλ λͺ¨μ κΈ°λ³Έ μ€μ (prefers-reduced-motion), μ¬μ§μ΄ μΈμ μ μ© λ μ΄μμκΉμ§ μ§μν΄μΌ ν©λλ€. μ΄λ¬ν λͺ¨λ λ³νμ κΈ°μ‘΄ λ°©μμΌλ‘ μ²λ¦¬νλ©΄ λ―Έλμ΄ μΏΌλ¦¬μ μ‘°κ±΄λΆ ν΄λμ€μ λ―Έλ‘λ‘ μ΄μ΄μ§ μ μμ΅λλ€.
μ‘°κ±΄λΆ λ μ΄μ΄ νμ±νλ μ°μν μ루μ μ μ 곡ν©λλ€. 컨ν μ€νΈλ₯Ό κΈ°λ°μΌλ‘ μ€νμΌμ λΆν νλ CSS λ€μ΄ν°λΈ μν€ν μ² ν¨ν΄μ μ 곡νμ¬ κ΄λ ¨ μ½λλ§ μ μ©λλλ‘ νμ¬ λ κ°λ³κ³ λΉ λ₯΄λ©° μ μ§ κ΄λ¦¬νκΈ° μ¬μ΄ μ ν리μΌμ΄μ μ λ§λλλ€.
"μ΄λ»κ²?" : μ‘°κ±΄λΆ λ μ΄μ΄ νμ±ν κΈ°λ²
λ μ΄μ΄μ μ€νμΌμ 쑰건λΆλ‘ μ μ©νκ±°λ κ°μ Έμ€λ λͺ κ°μ§ κ°λ ₯ν κΈ°λ²μ΄ μμ΅λλ€. μμ CSS μ루μ λΆν° JavaScript μ§μ λ°©λ²μ μ΄λ₯΄κΈ°κΉμ§ κ°μ₯ ν¨κ³Όμ μΈ μ κ·Ό λ°©μμ μ΄ν΄λ³΄κ² μ΅λλ€.
κΈ°λ² 1: λ μ΄μ΄ μ§μμ ν΅ν μ‘°κ±΄λΆ @import
@import κ·μΉμ΄ μ§ννμ΅λλ€. μ΄μ λ―Έλμ΄ μΏΌλ¦¬μ ν¨κ» μ¬μ©ν μ μμΌλ©°, μ€μνκ²λ @layer λΈλ‘ λ΄μ λ°°μΉν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ νΉμ μ‘°κ±΄μ΄ μΆ©μ‘±λ λλ§ μ 체 μ€νμΌμνΈλ₯Ό νΉμ λ μ΄μ΄λ‘ κ°μ Έμ¬ μ μμ΅λλ€.
μ΄λ λ€μν νλ©΄ ν¬κΈ°μ λν μ 체 CSSμ κ°μ λκ·λͺ¨ CSSλ₯Ό λ³λμ νμΌλ‘ λΆν νλ λ° νΉν μ μ©ν©λλ€. μ΄λ κ² νλ©΄ λ©μΈ μ€νμΌμνΈκ° κΉλνκ² μ μ§λκ³ μ½λ ꡬμ±μ΄ μ΄μ§λ©λλ€.
μμ: λ·°ν¬νΈλ³ λ μ΄μμ λ μ΄μ΄
λͺ¨λ°μΌ, νλΈλ¦Ώ λ° λ°μ€ν¬ν±μ λν λ€μν λ μ΄μμ μμ€ν μ΄ μλ€κ³ μμν΄ λ³΄μμμ€. κ° λ μ΄μ΄μ λν΄ λ μ΄μ΄λ₯Ό μ μνκ³ ν΄λΉ μ€νμΌμνΈλ₯Ό 쑰건λΆλ‘ κ°μ Έμ¬ μ μμ΅λλ€.
// main.css
// λ¨Όμ μμ ν λ μ΄μ΄ μμλ₯Ό μ€μ ν©λλ€.
@layer reset, base, layout-mobile, layout-tablet, layout-desktop, components;
// νμ νμ±νλλ λ μ΄μ΄
@layer reset { @import url("reset.css"); }
@layer base { @import url("base.css"); }
// ν΄λΉ λ μ΄μ΄λ‘ λ μ΄μμ μ€νμΌμ 쑰건λΆλ‘ κ°μ Έμ΅λλ€.
@layer layout-mobile {
@import url("layout-mobile.css") (width <= 767px);
}
@layer layout-tablet {
@import url("layout-tablet.css") (768px <= width <= 1023px);
}
@layer layout-desktop {
@import url("layout-desktop.css") (width >= 1024px);
}
μ₯μ :
- μ°μν κ΄μ¬μ¬ λΆλ¦¬: κ° μ»¨ν μ€νΈμ μ€νμΌμ μ체 νμΌμ μμ΄ νλ‘μ νΈ κ΅¬μ‘°λ₯Ό λͺ ννκ³ κ΄λ¦¬νκΈ° μ½κ² λ§λλλ€.
- μ μ¬μ μΌλ‘ λ λΉ λ₯Έ μ΄κΈ° λ‘λ: λΈλΌμ°μ λ νμ¬ μ»¨ν μ€νΈμ μΌμΉνλ μ€νμΌμνΈλ§ λ€μ΄λ‘λνλ©΄ λ©λλ€.
κ³ λ € μ¬ν:
- λ€νΈμν¬ μμ²: μ ν΅μ μΌλ‘ @importλ λ λλ§μ μ°¨λ¨νλ μμ°¨μ μΈ λ€νΈμν¬ μμ²μΌλ‘ μ΄μ΄μ§ μ μμ΅λλ€. κ·Έλ¬λ μ΅μ λΉλ λꡬ(Vite, Webpack, Parcel λ±)λ μ€λ§νΈν©λλ€. μ΄λ¬ν @import κ·μΉμ λΉλ μμ μ μ²λ¦¬νμ¬ λͺ¨λ κ²μ λ¨μΌ μ΅μ νλ CSS νμΌλ‘ λ²λ€λ§νλ©΄μλ λ―Έλμ΄ μΏΌλ¦¬λ‘ μ‘°κ±΄λΆ λ Όλ¦¬λ₯Ό μ‘΄μ€ν©λλ€. λΉλ λ¨κ³κ° μλ νλ‘μ νΈμ κ²½μ° μ΄ μ κ·Ό λ°©μμ μ£Όμν΄μ μ¬μ©ν΄μΌ ν©λλ€.
κΈ°λ² 2: λ μ΄μ΄ λΈλ‘ λ΄ μ‘°κ±΄λΆ κ·μΉ
μλ§λ κ°μ₯ μ§μ μ μ΄κ³ λ리 μ μ© κ°λ₯ν κΈ°λ²μ @media λ° @supportsμ κ°μ μ‘°κ±΄λΆ at-ruleμ λ μ΄μ΄ λΈλ‘ λ΄λΆμ λ°°μΉνλ κ²μ λλ€. μ‘°κ±΄λΆ λΈλ‘ λ΄μ λͺ¨λ κ·μΉμ ν΄λΉ λ μ΄μ΄μ μνκ³ μΊμ€μΌμ΄λ μμμμμ μμΉλ₯Ό μ‘΄μ€ν©λλ€.
μ΄ λ°©λ²μ λ³λμ νμΌ μμ΄ ν λ§, λ°μν μ‘°μ λ° μ μ§μ ν₯μκ³Ό κ°μ λ³νμ κ΄λ¦¬νλ λ° μλ²½ν©λλ€.
μμ 1: ν λ§ κΈ°λ° λ μ΄μ΄(λ°μ/μ΄λμ΄ λͺ¨λ)
μ΄λμ΄ λͺ¨λ μ¬μ μλ₯Ό ν¬ν¨νμ¬ λͺ¨λ μκ°μ ν λ§λ₯Ό μ²λ¦¬νκΈ° μν΄ μ μ© theme λ μ΄μ΄λ₯Ό λ§λ€κ² μ΅λλ€.
@layer base, theme, components;
@layer theme {
// κΈ°λ³Έ(λ°μ ν
λ§) λ³μ
:root {
--background-primary: #ffffff;
--text-primary: #212121;
--accent-color: #007bff;
}
// μ΄λμ΄ ν
λ§ μ¬μ μ, μ¬μ©μ κΈ°λ³Έ μ€μ μΌλ‘ νμ±ν
@media (prefers-color-scheme: dark) {
:root {
--background-primary: #121212;
--text-primary: #eeeeee;
--accent-color: #64b5f6;
}
}
}
μ¬κΈ°μ λͺ¨λ ν λ§ κ΄λ ¨ λ‘μ§μ theme λ μ΄μ΄ λ΄μ κΉλνκ² μΊ‘μνλ©λλ€. μ΄λμ΄ λͺ¨λ λ―Έλμ΄ μΏΌλ¦¬κ° νμ±νλλ©΄ ν΄λΉ κ·μΉμ΄ μ μ©λμ§λ§ theme λ μ΄μ΄μ μ°μ μμ μμ€μμ μλν©λλ€.
μμ 2: μ μ§μ ν₯μμ μν κΈ°λ₯ μ§μ λ μ΄μ΄
@supports κ·μΉμ μ μ§μ ν₯μμ μν κ°λ ₯ν λꡬμ λλ€. λ μ΄μ΄ λ΄μμ μ΄λ₯Ό μ¬μ©νμ¬ λΈλΌμ°μ κ° μ΄λ₯Ό μ§μνλ κ²½μ°μλ§ κ³ κΈ μ€νμΌμ μ μ©νλ λμμ λ€λ₯Έ λΈλΌμ°μ μ λν κ²¬κ³ ν ν΄λ°±μ 보μ₯ν μ μμ΅λλ€.
@layer base, components, enhancements;
@layer components {
// λͺ¨λ λΈλΌμ°μ μ λν ν΄λ°± λ μ΄μμ
.card-grid {
display: flex;
flex-wrap: wrap;
}
}
@layer enhancements {
// CSS Grid subgridλ₯Ό μ§μνλ λΈλΌμ°μ λ₯Ό μν κ³ κΈ λ μ΄μμ
@supports (grid-template-columns: subgrid) {
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
/* κΈ°ν κ³ κΈ κ·Έλ¦¬λ μμ± */
}
}
// backdrop-filterλ₯Ό μ§μνλ λΈλΌμ°μ λ₯Ό μν μ€νμΌ
@supports (backdrop-filter: blur(10px)) {
.modal-overlay {
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(10px);
}
}
}
enhancements λ μ΄μ΄κ° components μ΄νμ μ μλμκΈ° λλ¬Έμ λΈλΌμ°μ κ° κΈ°λ₯μ μ§μν λ ν΄λ°± μ€νμΌμ ν¨κ³Όμ μΌλ‘ μ¬μ μν©λλ€. μ΄κ²μ μ μ§μ ν₯μμ ꡬννλ κΉλνκ³ κ°λ ₯ν λ°©λ²μ λλ€.
κΈ°λ² 3: JavaScript κΈ°λ° μ‘°κ±΄λΆ νμ±ν(κ³ κΈ)
λλ‘λ μΈνΈ μ€νμΌμ νμ±ννκΈ° μν μ‘°κ±΄μ΄ CSSμμ μ¬μ©ν μ μμ΅λλ€. μ ν리μΌμ΄μ μν, μλ₯Ό λ€μ΄ μ¬μ©μ μΈμ¦, A/B ν μ€νΈ λ³ν λλ νμ΄μ§μ νμ¬ λ λλ§λλ λμ μ»΄ν¬λνΈμ κ°μ΄ JavaScriptμ λ°λΌ λ¬λΌμ§ μ μμ΅λλ€. μ΄λ¬ν κ²½μ° JavaScriptλ 격차λ₯Ό ν΄μνλ μλ²½ν λꡬμ λλ€.
ν΅μ¬μ CSSμμ λ μ΄μ΄ μμλ₯Ό 미리 μ μνλ κ²μ λλ€. μ΄κ²μ μΊμ€μΌμ΄λ ꡬ쑰λ₯Ό μ€μ ν©λλ€. κ·Έλ° λ€μ JavaScriptλ μ§μ λ μ¬μ μ μλ λ μ΄μ΄μ λν CSS κ·μΉμ ν¬ν¨νλ <style> νκ·Έλ₯Ό λμ μΌλ‘ μ½μ ν μ μμ΅λλ€.
μμ: "κ΄λ¦¬μ λͺ¨λ" ν λ§ λ μ΄μ΄ λ‘λ
κ΄λ¦¬μκ° μΆκ° UI μμμ λλ²κΉ ν λ리λ₯Ό 보λ μ½ν μΈ κ΄λ¦¬ μμ€ν μ μμν΄ λ³΄μμμ€. μ΄λ¬ν μ€νμΌμ λν μ μ© λ μ΄μ΄λ₯Ό λ§λ€κ³ κ΄λ¦¬μκ° λ‘κ·ΈμΈνμ λλ§ μ½μ ν μ μμ΅λλ€.
// main.css - μ 체 μ μ¬μ λ μ΄μ΄ μμλ₯Ό μ€μ ν©λλ€.
@layer reset, base, components, admin-mode, utilities;
// app.js - μ€νμΌ μ½μ
λ‘μ§
function initializeAdminMode(user) {
if (user.role === 'admin') {
const adminStyles = document.createElement('style');
adminStyles.id = 'admin-styles';
adminStyles.textContent = `
@layer admin-mode {
[data-editable] {
outline: 2px dashed hotpink;
position: relative;
}
[data-editable]::after {
content: 'Editable';
position: absolute;
top: -20px;
left: 0;
background-color: hotpink;
color: white;
font-size: 12px;
padding: 2px 4px;
}
}
`;
document.head.appendChild(adminStyles);
}
}
μ΄ μλ리μ€μμλ μΌλ° μ¬μ©μμ κ²½μ° admin-mode λ μ΄μ΄κ° λΉμ΄ μμ΅λλ€. κ·Έλ¬λ κ΄λ¦¬μ μ¬μ©μμκ² initializeAdminModeκ° νΈμΆλλ©΄ JavaScriptλ μ€νμΌμ ν΄λΉ μ¬μ μ μλ λ μ΄μ΄λ‘ μ§μ μ½μ ν©λλ€. admin-modeκ° components μ΄νμ μ μλμκΈ° λλ¬Έμ κ³ μ ν μ νμ μμ΄λ κΈ°λ³Έ μ»΄ν¬λνΈ μ€νμΌμ μ½κ³ μμΈ‘ κ°λ₯νκ² μ¬μ μν μ μμ΅λλ€.
λͺ¨λ κ²μ κ²°ν©: μ€μ κΈλ‘λ² μλ리μ€
κΈλ‘λ² μ μ μκ±°λ μΉμ¬μ΄νΈμ μ ν νμ΄μ§μ κ°μ 볡μ‘ν μ»΄ν¬λνΈμ λν CSS μν€ν μ²λ₯Ό μ€κ³ν΄ λ³΄κ² μ΅λλ€. μ΄ νμ΄μ§λ λ°μνμ΄μ΄μΌ νκ³ , ν λ§λ₯Ό μ§μν΄μΌ νλ©°, κΉλν μΈμ 보기λ₯Ό μ 곡νκ³ , A/B ν μ€νΈλ₯Ό μν νΉλ³ λͺ¨λλ₯Ό μ 곡ν΄μΌ ν©λλ€.
1λ¨κ³: λ§μ€ν° λ μ΄μ΄ μμ μ μ
λ¨Όμ λ©μΈ μ€νμΌμνΈμμ κ°λ₯ν λͺ¨λ λ μ΄μ΄λ₯Ό μ μν©λλ€. μ΄κ²μ΄ μ°λ¦¬μ μν€ν μ² μ²μ¬μ§μ λλ€.
@layer reset, // CSS μ¬μ€μ base, // μ μ μμ μ€νμΌ, κΈκΌ΄ λ± theme, // ν λ§ λ³μ(λ°μ/μ΄λμ΄/κΈ°ν) layout, // λ©μΈ νμ΄μ§ ꡬ쑰(그리λ, 컨ν μ΄λ) components, // μ¬μ¬μ© κ°λ₯ν μ»΄ν¬λνΈ μ€νμΌ(λ²νΌ, μΉ΄λ) page-specific, // μ ν νμ΄μ§ κ³ μ μ€νμΌ ab-test, // A/B ν μ€νΈ λ³νμ λν μ¬μ μ print, // μΈμλ³ μ€νμΌ utilities; // κ³ μ°μ μμ μ νΈλ¦¬ν° ν΄λμ€
2λ¨κ³: λ μ΄μ΄μμ μ‘°κ±΄λΆ λ Όλ¦¬ ꡬν
μ΄μ μ΄λ¬ν λ μ΄μ΄λ₯Ό μ±μ°κ³ νμν κ²½μ° μ‘°κ±΄λΆ κ·μΉμ μ¬μ©ν©λλ€.
// --- ν
λ§ λ μ΄μ΄ ---
@layer theme {
:root { --text-color: #333; }
@media (prefers-color-scheme: dark) {
:root { --text-color: #eee; }
}
}
// --- λ μ΄μμ λ μ΄μ΄(λͺ¨λ°μΌ μ°μ ) ---
@layer layout {
.product-page { display: flex; flex-direction: column; }
@media (min-width: 900px) {
.product-page { flex-direction: row; }
}
}
// --- μΈμ λ μ΄μ΄ ---
@layer print {
@media print {
header, footer, .buy-button {
display: none;
}
.product-image, .product-description {
width: 100%;
page-break-inside: avoid;
}
}
}
3λ¨κ³: JavaScript κΈ°λ° λ μ΄μ΄ μ²λ¦¬
A/B ν μ€νΈλ JavaScriptλ‘ μ μ΄λ©λλ€. μ¬μ©μκ° "new-design" λ³νμ μλ€λ©΄ ab-test λ μ΄μ΄μ μ€νμΌμ μ½μ ν©λλ€.
// A/B ν
μ€νΈ λ‘μ§μμ
if (user.abVariant === 'new-design') {
const testStyles = document.createElement('style');
testStyles.textContent = `
@layer ab-test {
.buy-button {
background-color: limegreen;
transform: scale(1.1);
}
.product-title {
font-family: 'Georgia', serif;
}
}
`;
document.head.appendChild(testStyles);
}
μ΄ μν€ν μ²λ λ§€μ° κ°λ ₯ν©λλ€. μΈμ μ€νμΌμ μΈμν λλ§ μ μ©λ©λλ€. μ΄λμ΄ λͺ¨λλ μ¬μ©μ κΈ°λ³Έ μ€μ μ λ°λΌ νμ±νλ©λλ€. A/B ν μ€νΈ μ€νμΌμ μΌλΆ μ¬μ©μμκ²λ§ λ‘λλλ©°, ab-test λ μ΄μ΄κ° components μ΄νμ μ€κΈ° λλ¬Έμ κΈ°λ³Έ λ²νΌ λ° μ λͺ© μ€νμΌμ μ½κ² μ¬μ μν μ μμ΅λλ€.
μ΄μ λ° λͺ¨λ² μ¬λ‘
μ‘°κ±΄λΆ λ μ΄μ΄ μ λ΅μ μ±ννλ©΄ μλΉν μ΄μ μ μ»μ μ μμ§λ§, ν¨κ³Όλ₯Ό κ·Ήλννλ €λ©΄ λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄λ κ²μ΄ μ€μν©λλ€.
μ£Όμ μ΄μ
- ν₯μλ μ±λ₯: λΈλΌμ°μ κ° μ¬μ©λμ§ μλ CSS κ·μΉμ ꡬ문 λΆμνμ§ λͺ»νλλ‘ νμ¬ μ΄κΈ° λ λλ§ μ°¨λ¨ μκ°μ μ€μ¬ λ λΉ λ₯΄κ³ μνν μ¬μ©μ κ²½νμ μ 곡ν©λλ€.
- ν₯μλ μ μ§ κ΄λ¦¬μ±: μ€νμΌμ λ¨μν μν μ»΄ν¬λνΈκ° μλλΌ μ»¨ν μ€νΈμ λͺ©μ λ³λ‘ ꡬμ±λ©λλ€. μ΄λ κ² νλ©΄ μ½λλ² μ΄μ€λ₯Ό μ΄ν΄, λλ²κΉ λ° νμ₯νκΈ°κ° λ μ¬μμ§λλ€.
- μμΈ‘ κ°λ₯ν νΉμμ±: λͺ μμ μΈ λ μ΄μ΄ μμλ νΉμμ± μΆ©λμ μ κ±°ν©λλ€. μ΄λ€ λ μ΄μ΄μ μ€νμΌμ΄ μ΄κΈΈμ§ νμ μ μ μμΌλ―λ‘ μμ νκ³ μμ μκ² μ¬μ μν μ μμ΅λλ€.
- κΉλν μ μ λ²μ: λ μ΄μ΄λ μ»΄ν¬λνΈ μμ€ μ€νμΌκ³Ό μΆ©λνκ±°λ λ²μλ₯Ό μ€μΌμν€μ§ μκ³ μ μ μ€νμΌ(ν λ§ λ° λ μ΄μμκ³Ό κ°μ)μ κ΄λ¦¬νλ ꡬ쑰νλ λ°©λ²μ μ 곡ν©λλ€.
λͺ¨λ² μ¬λ‘
- μ 체 λ μ΄μ΄ μμλ₯Ό 미리 μ μνμμμ€: νμ λ©μΈ μ€νμΌμνΈ μλ¨μ λ¨μΌ @layer λ¬Έμμ λͺ¨λ μ μ¬μ λ μ΄μ΄λ₯Ό μ μΈνμμμ€. μ΄λ κ² νλ©΄ μ ν리μΌμ΄μ μ 체μ μΊμ€μΌμ΄λ μμμ λν μ μΌν μ§μ€ 곡κΈμμ΄ μμ±λ©λλ€.
- μν€ν μ²μ μΌλ‘ μκ°νμμμ€: μ»΄ν¬λνΈ λ³νμ λ―ΈμΈ μμ€μ΄ μλ κ΄λ²μν μν€ν μ² κ΄λ ¨(μ¬μ€μ , κΈ°λ³Έ, ν λ§, λ μ΄μμ)μ λ μ΄μ΄λ₯Ό μ¬μ©νμμμ€. λ¨μΌ μ»΄ν¬λνΈμ μμ λ³νμ κ²½μ° κΈ°μ‘΄ ν΄λμ€κ° μ¬μ ν λ λμ μ νμ λλ€.
- λͺ¨λ°μΌ μ°μ μ κ·Ό λ°©μ μ±ν: λ μ΄μ΄ λ΄μμ λͺ¨λ°μΌ λ·°ν¬νΈμ λν κΈ°λ³Έ μ€νμΌμ μ μν©λλ€. κ·Έλ° λ€μ λμΌν λ μ΄μ΄ λλ νμ λ μ΄μ΄ λ΄μμ @media (min-width: ...) 쿼리λ₯Ό μ¬μ©νμ¬ λ ν° νλ©΄μ λν μ€νμΌμ μΆκ°νκ±°λ μ¬μ μν©λλ€.
- λΉλ λꡬ νμ©: μ΅μ λΉλ λꡬλ₯Ό μ¬μ©νμ¬ CSSλ₯Ό μ²λ¦¬νμμμ€. μ΄λ κ² νλ©΄ @import λ¬Έμ΄ μ¬λ°λ₯΄κ² λ²λ€λ§λκ³ μ½λκ° μΆμλλ©° λΈλΌμ°μ μ μ΅μ νλ μ λ¬μ΄ 보μ₯λ©λλ€.
- λ μ΄μ΄ μ λ΅ λ¬Έμν: λͺ¨λ 곡λ νλ‘μ νΈμ λν΄ λͺ νν λ¬Έμκ° νμμ μ λλ€. κ° λ μ΄μ΄μ λͺ©μ , μΊμ€μΌμ΄λμμμ μμΉ λ° νμ±νλλ 쑰건μ λν κ°μ΄λλ₯Ό λ§λμμμ€.
κ²°λ‘ : CSS μν€ν μ²μ μλ‘μ΄ μλ
CSS μΊμ€μΌμ΄λ λ μ΄μ΄λ νΉμμ±μ κ΄λ¦¬νλ μλ‘μ΄ λꡬ μ΄μμ λλ€. λ μ§λ₯μ μ΄κ³ λμ μ΄λ©° μ±λ₯μ΄ λ°μ΄λ μ€νμΌ μμ± λ°©μμΌλ‘μ κ΄λ¬Έμ λλ€. λ μ΄μ΄λ₯Ό μ‘°κ±΄λΆ λ Όλ¦¬(λ―Έλμ΄ μΏΌλ¦¬, μ§μ 쿼리 λλ JavaScriptλ₯Ό ν΅ν)μ κ²°ν©ν¨μΌλ‘μ¨ μ¬μ©μ λ° νκ²½μ μλ²½νκ² μ μνλ μν© μΈμ μ€νμΌλ§ μμ€ν μ ꡬμΆν μ μμ΅λλ€.
μ΄ μ κ·Ό λ°©μμ κ±°λν μΌμ²΄ν μ€νμΌμνΈμμ λ²μ΄λ λ μμ μ μ΄κ³ ν¨μ¨μ μΈ λ°©λ²λ‘ μΌλ‘ λμκ°λλ€. μ μΈκ³ μ¬μ©μλ₯Ό μν 볡μ‘νκ³ κΈ°λ₯μ΄ νλΆν μ ν리μΌμ΄μ μ λ§λ€ μ μκ² ν΄μ£Όλ©΄μλ κ°λ³κ³ λΉ λ₯΄λ©° μ¦κ²κ² μ μ§ κ΄λ¦¬ν μ μμ΅λλ€. λ€μ νλ‘μ νΈλ₯Ό μμν λ μ‘°κ±΄λΆ λ μ΄μ΄ μ λ΅μ΄ CSS μν€ν μ²λ₯Ό μ΄λ»κ² ν₯μμν¬ μ μλμ§ κ³ λ €ν΄ λ³΄μμμ€. μ€νμΌλ§μ λ―Έλλ λ¨μν μ‘°μ§νλ κ²μ΄ μλλΌ μν© μΈμμ λλ€.